module.exports = function (app) {
    const mongooseClient = app.get('mongooseClient');
    const { Schema } = mongooseClient;
    const { workflowSchema } = require('./workflows.model');
  
    const operationStageSchema = new Schema({
      name: { type: String, required: true },//ready, start, end is embed, can add more
      display_name: { type: String},
      start: { 
        time: { type: Number } //pervious time: positive before current time, forever: negative
      },
      end: {
        time: { type: Number } //pervious time: positive before current time, forever: negative
      },
      expire: {
        time: { type: Number } //pervious time: positive before current time, forever: negative
      },
      data: { type: Schema.Types.Mixed }
    }, {
      timestamps: true
    });
  
    const operationRoleSchema = new Schema({
      oid: { type: Schema.Types.ObjectId },
      name: { type: String },// usually name should with org
      org: { 
        oid: { type: Schema.Types.ObjectId },
        name: { type: String }
       },
      include: {
        roles: [ roleSchema ],//other roles objectId
        recursive_roles: [ roleSchema ],
        children: { type: String, enum: ['recursive','true','false'] },
        parent: { type: String, enum: ['recursive','true','false'] },
      },
      exclude: {
        roles: [ roleSchema ],
        recursive_roles: [ roleSchema ],
        children: { type: String, enum: ['recursive','true','false'] },
        parent: { type: String, enum: ['recursive','true','false'] },
      },
      data: { type: Schema.Types.Mixed }
    }, {
      timestamps: true
    });

    const operationMessageSchema = new Schema({
      name: { type: String },// usually name should with org
      title: { type: String },
      description: { type: String },
      contents: [ { type: Schema.Types.Mixed } ],
      status: { type: String, enum: ['sended', 'saved', 'received']},
      to: {
        operations: [
          { 
            oid: { type: Schema.Types.ObjectId },
            filters: [{ type: Schema.Types.Mixed }], //filter to operators of operation
            data: { type: Schema.Types.Mixed }
          }
        ], // send all operation
        operators: [
          { 
            oid: { type: Schema.Types.ObjectId },
            data: { type: Schema.Types.Mixed }
          }
        ]
      },
      from: {
        operator: {
          oid: { type: Schema.Types.ObjectId },
          data: { type: Schema.Types.Mixed }
        }
      }
    }, {
      timestamps: true
    });

    const operationAlertSchema = new Schema({
      name: { type: String },
      title: { type: String },
      description: { type: String },
      contents: [ { type: Schema.Types.Mixed } ],
      alert_for_time: { type: Schema.Types.Date },
      to: {
        operations: [
          { 
            oid: { type: Schema.Types.ObjectId },
            filters: [{ type: Schema.Types.Mixed }], //filter to operators of operation
            data: { type: Schema.Types.Mixed }
          }
        ], // send all operation operators
        operators: [
          { 
            oid: { type: Schema.Types.ObjectId },
            data: { type: Schema.Types.Mixed }
          }
        ]
      },
      from: {
        operator: {
          oid: { type: Schema.Types.ObjectId },
          data: { type: Schema.Types.Mixed }
        }
      },
      reminders: [
        {
          start: {
            time: { type: Schema.Types.Date },
            expression: { type: String } //like alert_for_time - 5d(before alert for time 5 days )
          },
          end: { 
            time: { type: Schema.Types.Date },
            expression: { type: String } //like alert_for_time - 5d(before alert for time 5 days )
          },
          interval:{
            period: { type: String }, //year(y), month(m), week(w), day(d), hour(h), minute(m), second(s), milisecond(ms),
            number: { type: Number }, //times to divid from start to end
          },
          repeat: {
            period: { type: String }, //year(y), month(m), week(w), day(d), hour(h), minute(m), second(s), milisecond(ms),
            number: { type: Number }, //times to repeat
          },
          data: { type: Schema.Types.Mixed }, //use to override info from alert
          levels: {
            type: Schema.Types.Mixed
          } //can override alert levels
        }
      ],
      levels: { //level will be populated by client base on levels
        urgent: { type: String },//for example: now - alert_for_time < 1d(1h,1m)
        warn: { type: String },
        info: { type: String }
       },//urgent, warn, info or other
      data: { type: Schema.Types.Mixed }
    }, {
      timestamps: true
    });

    const objectInOrgSchema = new Schema({
      oid: { type: Schema.Types.ObjectId },
      name: String,
      org: { 
        oid: { type: Schema.Types.ObjectId },
        name: String
      },
      data: { type: Schema.Types.Mixed }
    });

    const workSchema = new Schema({
      queue: Number,//when add new work, should re-caculate queue
      name: { type: String, required: true },
      display_name: { type: String },
      progress:{ type: progressSchema },
      operations: [
        { type: objectInOrgSchema }
      ],
      works: [ { type: workSchema } ],
      workflows: [ { type: workflowSchema }],
      data:{ type: Schema.Types.Mixed } //some condition data define here
    });

    const workflowSchema = new Schema({
      name: { type: String, required: true },
      display_name: { type: String },
      description: { type: String },
      works: [
        {
          type: workSchema
        }
      ]
    }, {
      timestamps: true
    });

    const processDataSchema = new Schema({
      percentage: Number,
      time: { type: Schema.Types.Date },
      data: { type: Schema.Types.Mixed }
    }, {
      timestamps: true
    });

    const progressSchema = new Schema({
      percentage: Number,
      processData: [{ type: processDataSchema }],
      data: {
        type: Schema.Types.Mixed
      }
    })
  
    return {
        operationStageSchema,operationRoleSchema,operationMessageSchema,
        objectInOrgSchema, workflowSchema, progressSchema
    }
  };